package ospf

import (
	qsmessage "ConvertFlow/message"
	"encoding/binary"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"github.com/schollz/progressbar/v3"
)

// OSPF 常量定义
const (
	DefaultSnapLen = 65535
	DefaultTimeout = pcap.BlockForever
)

// OSPFPacketType OSPF数据包类型
type OSPFPacketType uint8

// PacketProcessor 数据包处理器接口
type PacketProcessor interface {
	ProcessPacket(packet gopacket.Packet) error
}

// OSPFServer 结构体定义
type OSPFServer struct {
	handle      *pcap.Handle
	localIP     net.IP
	routerID    uint32
	ifaceName   string
	stopChan    chan struct{}
	wg          sync.WaitGroup
	mu          sync.Mutex
	packetCount int64
	processor   PacketProcessor
}

// NewOSPFServer 创建新的OSPF服务器实例
func NewOSPFServer(ifaceName string, localIP net.IP, processor PacketProcessor) (*OSPFServer, error) {
	handle, err := pcap.OpenLive(ifaceName, DefaultSnapLen, true, DefaultTimeout)
	if err != nil {
		return nil, fmt.Errorf("failed to open interface: %v", err)
	}

	if err := handle.SetBPFFilter("proto ospf"); err != nil {
		handle.Close()
		return nil, fmt.Errorf("failed to set BPF filter: %v", err)
	}

	return &OSPFServer{
		handle:    handle,
		localIP:   localIP,
		routerID:  binary.BigEndian.Uint32(localIP.To4()),
		ifaceName: ifaceName,
		stopChan:  make(chan struct{}),
		processor: processor,
	}, nil
}

// ParseOSPFHeader 解析OSPF头部
func ParseOSPFHeader(payload []byte) (*OSPFv2, error) {
	if len(payload) < OSPFv2HeaderLength {
		return nil, fmt.Errorf("packet too short for OSPF header")
	}

	ospf := &OSPFv2{
		BaseLayer: layers.BaseLayer{
			Contents: payload[:OSPFv2HeaderLength],
			Payload:  payload[OSPFv2HeaderLength:],
		},
		Version:        payload[0],
		Type:           payload[1],
		PacketLength:   binary.BigEndian.Uint16(payload[2:4]),
		RouterID:       binary.BigEndian.Uint32(payload[4:8]),
		AreaID:         binary.BigEndian.Uint32(payload[8:12]),
		Checksum:       binary.BigEndian.Uint16(payload[12:14]),
		AuType:         binary.BigEndian.Uint16(payload[14:16]),
		Authentication: binary.BigEndian.Uint64(payload[16:24]),
		Contents:       payload[24:],
	}

	return ospf, nil
}

// ParseOSPFHello 解析OSPF Hello包
func ParseOSPFHello(payload []byte) (*OSPFv2Hello, error) {
	if len(payload) < HelloPacketMinLength {
		return nil, fmt.Errorf("packet too short for OSPF Hello")
	}

	hello := &OSPFv2Hello{
		BaseLayer: layers.BaseLayer{
			Contents: payload[:HelloPacketMinLength],
			Payload:  payload[HelloPacketMinLength:],
		},
		NetworkMask:   binary.BigEndian.Uint32(payload[0:4]),
		HelloInterval: binary.BigEndian.Uint16(payload[4:6]),
		Options:       payload[6],
		Priority:      payload[7],
		DeadInterval:  binary.BigEndian.Uint32(payload[8:12]),
		DR:            binary.BigEndian.Uint32(payload[12:16]),
		BDR:           binary.BigEndian.Uint32(payload[16:20]),
	}

	// 解析邻居列表
	remainingBytes := len(payload[20:])
	if remainingBytes > 0 && remainingBytes%4 == 0 {
		neighborCount := remainingBytes / 4
		hello.Neighbors = make([]uint32, neighborCount)
		for i := 0; i < neighborCount; i++ {
			start := HelloPacketMinLength + (i * 4)
			hello.Neighbors[i] = binary.BigEndian.Uint32(payload[start : start+4])
		}
	}

	return hello, nil
}

// GetMessageSizeAndSender 获取OSPF消息大小和发送者信息
func GetMessageSizeAndSender(ifaceName string) (size int, sender string, err error) {
	handle, err := pcap.OpenLive(ifaceName, DefaultSnapLen, true, DefaultTimeout)
	if err != nil {
		return 0, "", fmt.Errorf("failed to open interface: %v", err)
	}
	defer handle.Close()

	if err := handle.SetBPFFilter("proto ospf"); err != nil {
		return 0, "", fmt.Errorf("failed to set BPF filter: %v", err)
	}

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	packet := <-packetSource.Packets()

	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer == nil {
		return 0, "", fmt.Errorf("not an IPv4 packet")
	}
	ip, _ := ipLayer.(*layers.IPv4)
	sender = ip.SrcIP.String()

	applicationLayer := packet.ApplicationLayer()
	if applicationLayer == nil {
		return 0, "", fmt.Errorf("no OSPF data found")
	}

	ospfHeader, err := ParseOSPFHeader(applicationLayer.Payload())
	if err != nil {
		return 0, "", err
	}

	size, err = extractSizeFromPacket(ospfHeader)
	if err != nil {
		return 0, sender, err
	}

	return size, sender, nil
}

// extractSizeFromPacket 从不同类型的OSPF包中提取大小信息
func extractSizeFromPacket(ospf *OSPFv2) (int, error) {
	switch ospf.Type {
	case OSPFHello:
		hello, err := ParseOSPFHello(ospf.Payload)
		if err != nil {
			return 0, err
		}
		return int(hello.DeadInterval), nil

	case OSPFDatabaseDesc:
		if len(ospf.Payload) < 8 {
			return 0, fmt.Errorf("DD packet too short")
		}
		return int(binary.BigEndian.Uint32(ospf.Payload[4:8])), nil

	case OSPFLinkStateReq:
		if len(ospf.Payload) < 12 {
			return 0, fmt.Errorf("LSR packet too short")
		}
		return int(binary.BigEndian.Uint32(ospf.Payload[4:8])), nil

	case OSPFLinkStateUpd:
		if len(ospf.Payload) < 4 {
			return 0, fmt.Errorf("LSU packet too short")
		}
		return int(binary.BigEndian.Uint32(ospf.Payload[0:4])), nil

	case OSPFLinkStateAck:
		if len(ospf.Payload) < 20 {
			return 0, fmt.Errorf("LSAck packet too short")
		}
		return int(binary.BigEndian.Uint32(ospf.Payload[4:8])), nil

	default:
		return 0, fmt.Errorf("unknown OSPF packet type: %d", ospf.Type)
	}
}

// ParseOSPFPacket 解析OSPF数据包的详细信息
func ParseOSPFPacket(packet gopacket.Packet) (packetInfo map[string]interface{}, err error) {
	packetInfo = make(map[string]interface{})

	// 获取IP层信息
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer == nil {
		return nil, fmt.Errorf("not an IPv4 packet")
	}
	ip, _ := ipLayer.(*layers.IPv4)
	packetInfo["src_ip"] = ip.SrcIP.String()
	packetInfo["dst_ip"] = ip.DstIP.String()

	// 获取OSPF数据
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer == nil {
		return nil, fmt.Errorf("no OSPF data found")
	}

	payload := applicationLayer.Payload()
	if len(payload) < OSPFv2HeaderLength {
		return nil, fmt.Errorf("OSPF packet too short")
	}

	// 解析OSPF头部
	ospfHeader := &OSPFv2{
		Version:        payload[0],
		Type:           payload[1],
		PacketLength:   binary.BigEndian.Uint16(payload[2:4]),
		RouterID:       binary.BigEndian.Uint32(payload[4:8]),
		AreaID:         binary.BigEndian.Uint32(payload[8:12]),
		Checksum:       binary.BigEndian.Uint16(payload[12:14]),
		AuType:         binary.BigEndian.Uint16(payload[14:16]),
		Authentication: binary.BigEndian.Uint64(payload[16:24]),
	}

	packetInfo["version"] = ospfHeader.Version
	packetInfo["type"] = ospfHeader.Type
	packetInfo["packet_length"] = ospfHeader.PacketLength
	packetInfo["router_id"] = ospfHeader.RouterID
	packetInfo["area_id"] = ospfHeader.AreaID

	return packetInfo, nil
}

// getPacket 获取单个数据包并处理
func getPacket(packetSource *gopacket.PacketSource, data []string, indexes map[int]int) {
	packet := <-packetSource.Packets()

	// 获取OSPF数据
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer == nil {
		fmt.Println("No OSPF data found")
		return
	}

	payload := applicationLayer.Payload()
	ospfHeader, err := ParseOSPFHeader(payload)
	if err != nil {
		fmt.Println("Failed to parse OSPF header:", err)
		return
	}

	if ospfHeader.Type == OSPFHello {
		hello, err := ParseOSPFHello(ospfHeader.Contents)
		if err != nil {
			fmt.Println("Failed to parse OSPF Hello:", err)
			return
		}

		msg, index := qsmessage.Unmarshall(fmt.Sprintf("%d", hello.DeadInterval))
		if index >= 0 && index < len(data) {
			data[index] = msg
			delete(indexes, index)
		}
	}
}

// getPacketAndBarUpdate 获取单个数据包并更新进度条
func getPacketAndBarUpdate(packetSource *gopacket.PacketSource, data []string, indexes map[int]int, bar *progressbar.ProgressBar) {
	packet := <-packetSource.Packets()

	// 获取OSPF数据
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer == nil {
		fmt.Println("No OSPF data found")
		return
	}

	payload := applicationLayer.Payload()
	ospfHeader, err := ParseOSPFHeader(payload)
	if err != nil {
		fmt.Println("Failed to parse OSPF header:", err)
		return
	}

	if ospfHeader.Type == OSPFHello {
		hello, err := ParseOSPFHello(ospfHeader.Contents)
		if err != nil {
			fmt.Println("Failed to parse OSPF Hello:", err)
			return
		}

		msg, index := qsmessage.Unmarshall(fmt.Sprintf("%d", hello.DeadInterval))
		if index >= 0 && index < len(data) {
			data[index] = msg
			delete(indexes, index)
			err := bar.Add(1)
			if err != nil {
				return
			}
		}
	}
}

// ServeTemporary OSPF服务器等待特定数量的数据包，但在(n+2)*delay秒后停止工作
// 返回拼接的数据字符串和缺失的数据包索引
func ServeTemporary(listenAddr string, n int, progressBar bool, delay int) (data string, missingPacketIndexes []int) {
	// 进度条
	var bar *progressbar.ProgressBar
	if progressBar {
		bar = progressbar.Default(int64(n))
	}
	// 创建OSPF监听器
	handle, err := pcap.OpenLive(listenAddr, 65535, true, pcap.BlockForever)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer handle.Close()
	// 设置OSPF过滤器
	err = handle.SetBPFFilter("proto ospf")
	if err != nil {
		fmt.Println("Error setting BPF filter:", err)
		return
	}
	dataChunked := make([]string, n)
	indexes := make(map[int]int) // 使用map存储索引，删除元素的复杂度为O(1)
	for i := 0; i < n; i++ {
		indexes[i] = 0 // 值没有实际意义
	}
	// 创建数据包源
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	// 启动goroutine接收数据
	for i := 0; i < n; i++ {
		if progressBar {
			go getPacketAndBarUpdate(packetSource, dataChunked, indexes, bar)
		} else {
			go getPacket(packetSource, dataChunked, indexes)
		}
	}
	// 计时器，不会无限等待
	counter := (n + 2) * delay // 给一些额外的偏移量
	time.Sleep(time.Duration(counter) * time.Second)
	// 拼接数据
	data = strings.Join(dataChunked, "")
	// 获取缺失的数据包索引
	missingPacketIndexes = make([]int, 0, len(indexes))
	for index := range indexes {
		missingPacketIndexes = append(missingPacketIndexes, index)
	}

	return data, missingPacketIndexes
}

func Serve(listenAddr string, n int, progressBar bool) (data string, missingPacketIndexes []int) {
	var bar *progressbar.ProgressBar
	if progressBar {
		bar = progressbar.Default(int64(n))
	}

	// 创建OSPF监听器
	handle, err := pcap.OpenLive(listenAddr, 65535, true, pcap.BlockForever)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer handle.Close()

	// 设置OSPF过滤器
	err = handle.SetBPFFilter("proto ospf")
	if err != nil {
		fmt.Println("Error setting BPF filter:", err)
		return
	}

	dataChunked := make([]string, n)
	indexes := make(map[int]int)
	for i := 0; i < n; i++ {
		indexes[i] = 0
	}

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	packetSource.NoCopy = true // 优化性能

	var wg sync.WaitGroup
	wg.Add(n)
	for i := 0; i < n; i++ {
		go func(i int) {
			defer wg.Done()
			if progressBar {
				getPacketAndBarUpdate(packetSource, dataChunked, indexes, bar)
			} else {
				getPacket(packetSource, dataChunked, indexes)
			}
		}(i)
	}
	wg.Wait()

	data = strings.Join(dataChunked, "")
	missingPacketIndexes = make([]int, 0, len(indexes))
	for index := range indexes {
		missingPacketIndexes = append(missingPacketIndexes, index)
	}
	return data, missingPacketIndexes
}
